home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload Trio 2 / Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO / dir37 / ms_sh23s.zip / SRC / PS.C < prev    next >
C/C++ Source or Header  |  1994-08-28  |  21KB  |  966 lines

  1. /*
  2.  * Print OS/2 2.x process information
  3.  *
  4.  * usage: ps [ -L name ] [ -D name ] [ -SMm ] [[ -Ftnl ] pid]
  5.  *
  6.  *  -L Name    Load process info from file name
  7.  *  -D Name    Dump process info to file name
  8.  *  -S        Display Semaphore info
  9.  *  -M        Display Shared memory info
  10.  *  -m        Display Module info
  11.  *  -F        Display Full Names
  12.  *  -l        Display long info
  13.  *  -t        Display Thread Info
  14.  *  -a        Display All processes
  15.  *  -n        Do not display process trees
  16.  *  -o        Order process info
  17.  *
  18.  *  pid        The process id or name
  19.  *
  20.  *    $Header: /usr/users/istewart/shell/sh2.3/Release/RCS/ps.c,v 1.6 1994/08/28 15:18:03 istewart Exp $
  21.  *
  22.  *    $Log: ps.c,v $
  23.  * Revision 1.6  1994/08/28  15:18:03  istewart
  24.  * Fix display (end of list detection)
  25.  *
  26.  * Revision 1.5  1994/08/25  20:49:11  istewart
  27.  * MS Shell 2.3 Release
  28.  *
  29.  * Revision 1.4  1993/08/25  16:04:22  istewart
  30.  * Formatting change
  31.  *
  32.  * Revision 1.3  1993/07/02  10:21:35  istewart
  33.  * 224 Beta fixes
  34.  *
  35.  * Revision 1.2  1993/06/14  11:02:07  istewart
  36.  * More changes for 223 beta
  37.  *
  38.  * Revision 1.1  1993/06/02  09:52:35  istewart
  39.  * Beta 223 Updates - see Notes file
  40.  *
  41.  */
  42.  
  43. #include <sys/types.h>
  44. #include <sys/stat.h>
  45. #include <stdio.h>
  46. #include <stdlib.h>
  47. #include <unistd.h>
  48. #include <limits.h>
  49. #include <string.h>
  50. #include <fcntl.h>
  51. #include <ctype.h>
  52.  
  53. #define INCL_DOSSESMGR
  54. #define INCL_DOSPROCESS
  55. #define INCL_DOSMODULEMGR
  56. #include <os2.h>
  57.  
  58. #ifdef __OS2__
  59. #  pragma linkage        (DosQProcStatus, far16 pascal)
  60. #  pragma linkage        (DosGetPrty, far16 pascal)
  61.  
  62. extern USHORT            DosQProcStatus (PVOID, USHORT);
  63. extern USHORT            DosGetPrty (USHORT, PUSHORT, USHORT);
  64.  
  65. #  defined Dos32GetPrty        DosGetPrty
  66. #  defined Dos32QProcStatus    DosQProcStatus
  67. #  define PTR(ptr)        (ptr)
  68.  
  69. #elif defined (__EMX__)
  70.  
  71. USHORT                _THUNK_FUNCTION (Dos16GetPrty) ();
  72. USHORT                _THUNK_FUNCTION (Dos16QProcStatus) ();
  73.  
  74. #  define PTR(ptr)        (ptr)
  75.  
  76. extern USHORT            Dos32QProcStatus (PVOID, USHORT);
  77. extern USHORT            Dos32GetPrty (USHORT, PUSHORT, USHORT);
  78.  
  79. #else
  80.  
  81. #  define Dos32QProcStatus    DosQProcStatus
  82. #  define Dos32GetPrty        DosGetPrty
  83.  
  84. extern USHORT APIENTRY        DosQProcStatus (PVOID, USHORT);
  85.  
  86. #define PTR(ptr)    ((void *)((((ULONG)BasePS) & 0xFFFF0000L) |    \
  87.                   (((ULONG)(ptr))  & 0x0000FFFFL) ))
  88. #endif
  89.  
  90. /* Process Status structures */
  91.  
  92. #define PROCESS_END_INDICATOR    3
  93.  
  94. #pragma pack(1)
  95.  
  96. typedef struct _SUMMARY
  97. {
  98.     ULONG    ulThreadCount;        /* Number of threads in system    */
  99.     ULONG    ulProcessCount;        /* Number of processes in system*/
  100.     ULONG    ulModuleCount;        /* Number of modules in system    */
  101. } SUMMARY, *PSUMMARY;
  102.  
  103. /*
  104.  * Thread information
  105.  */
  106.  
  107. typedef struct _THREADINFO
  108. {
  109.     ULONG    ulRecType;        /* Record type (thread = 100)    */
  110.     USHORT    tidWithinProcess;    /* TID within process (TID is    */
  111.                         /* 4 bytes!!)            */
  112.     USHORT    usSlot;            /* Unique thread slot number    */
  113.     ULONG    ulBlockId;        /* Sleep id thread is sleeping on*/
  114.     ULONG    ulPriority;        /* Priority            */
  115.     ULONG    ulSysTime;        /* Thread System Time        */
  116.     ULONG    ulUserTime;        /* Thread User Time        */
  117.     UCHAR    uchState;        /* 1=ready,2=blocked,5=running    */
  118.     UCHAR    uchPad;            /* Filler            */
  119.     USHORT    usPad;            /* Filler            */
  120. } THREADINFO, *PTHREADINFO;
  121.  
  122. /*
  123.  * Process information
  124.  */
  125.  
  126. typedef struct _PROCESSINFO
  127. {
  128.     ULONG    ulEndIndicator;        /* 1 means not end, 3 means    */
  129.                         /* last entry            */
  130.     PTHREADINFO    ptiFirst;        /* Address of the 1st Thread    */
  131.                         /* Control Blk            */
  132.     USHORT    pid;            /* Process ID (2 bytes - PID    */
  133.                         /* is 4 bytes)            */
  134.     USHORT    pidParent;        /* Parent's process ID        */
  135.     ULONG    ulType;            /* Process Type            */
  136.     ULONG    ulStatus;        /* Process Status        */
  137.     ULONG    idSession;        /* Session ID            */
  138.     USHORT    hModRef;        /* Module handle of EXE        */
  139.     USHORT    usThreadCount;        /* Number of threads in this    */
  140.                         /* process            */
  141.     ULONG    ulSessionType;        /* Session Type            */
  142.     PVOID    pvReserved;        /* Unknown            */
  143.     USHORT    usSem16Count;        /* Number of 16-bit system    */
  144.                         /* semaphores            */
  145.     USHORT    usDllCount;        /* Number of Dlls used by    */
  146.                         /* process            */
  147.     USHORT    usShrMemHandles;    /* Number of shared memory    */
  148.                         /* handles            */
  149.     USHORT    usReserved;        /* Unknown            */
  150.     PUSHORT    pusSem16TableAddr;    /* Address of a 16-bit semaphore*/
  151.                         /* table            */
  152.     PUSHORT    pusDllTableAddr;    /* Address of a Dll table    */
  153.     PUSHORT    pusShrMemTableAddr;    /* Address of a shared memory    */
  154.                         /* table            */
  155. } PROCESSINFO, *PPROCESSINFO;
  156.  
  157. /*
  158.  * Semaphore info
  159.  */
  160.  
  161. typedef struct _SEMINFO
  162. {
  163.     struct _SEMINFO *pNext;        /* Ptr to next block        */
  164.     USHORT    idOwningThread;        /* ID of owning thread?        */
  165.     UCHAR    fbFlags;        /* Semaphore flags        */
  166.     UCHAR    uchReferenceCount;    /* Number of references        */
  167.     UCHAR    uchRequestCount;    /* Number of requests        */
  168.     UCHAR    ucReserved[3];        /* Unknown            */
  169.     USHORT    usIndex;        /* Index            */
  170.     CHAR    szSemName[ 1 ];        /* ASCIIZ semaphore name    */
  171. } SEMINFO, *PSEMINFO;
  172.  
  173. /*
  174.  * Shared memory info
  175.  */
  176.  
  177. typedef struct _SHRMEMINFO
  178. {
  179.     struct _SHRMEMINFO    *pNext;        /* Ptr to next block        */
  180.     USHORT    usMemHandle;        /* Shared memory handle (?)    */
  181.     SEL        selMem;            /* Selector            */
  182.     USHORT    usReferenceCount;    /* Number of references        */
  183.     CHAR    szMemName[ 1 ];        /* ASCIIZ shared memory name    */
  184. } SHRMEMINFO, *PSHRMEMINFO;
  185.  
  186. /*
  187.  * Module info
  188.  */
  189.  
  190. typedef struct _MODINFO
  191. {
  192.     struct _MODINFO    *pNext;    /* Ptr to next block (NULL on last one)    */
  193.     USHORT    hMod;        /* Module handle            */
  194.     USHORT    usModType;    /* Module type (0=16bit,1=32bit)    */
  195.     ULONG    ulModRefCount;    /* Count of module references        */
  196.     ULONG    ulSegmentCount;    /* Number of segments in module        */
  197.     ULONG    ulDontKnow1;    /*                    */
  198.     PSZ        szModName;    /* Addr of fully qualified module name    */
  199.     USHORT    usModRef[ 1 ];    /* Handles of module references        */
  200. } MODINFO, *PMODINFO;
  201.  
  202. /*
  203.  * header
  204.  */
  205.  
  206. typedef struct _BUFFHEADER
  207. {
  208.     PSUMMARY    psumm;        /* SUMMARY section ptr            */
  209.     PPROCESSINFO ppi;        /* PROCESS section ptr            */
  210.     PSEMINFO    psi;        /* SEM section ptr (add 16 to offset)    */
  211.     PVOID    pDontKnow1;    /*                    */
  212.     PSHRMEMINFO    psmi;        /* SHARED MEMORY section ptr        */
  213.     PMODINFO    pmi;        /* MODULE section ptr            */
  214.     PVOID    pDontKnow2;    /*                    */
  215.     PVOID    pDontKnow3;    /*                    */
  216. } BUFFHEADER, *PBUFFHEADER;
  217.  
  218. #pragma pack()
  219.  
  220. /*
  221.  * Associated functions
  222.  */
  223.  
  224. void        PrintProcessEntry (PPROCESSINFO, USHORT, PBUFFHEADER);
  225. void        RemoveProcessEntry (USHORT);
  226. int        SortProcesses (const void *, const void *);
  227. void        DisplayAllProcess (PBUFFHEADER);
  228. PPROCESSINFO    FindPidEntry (PBUFFHEADER, USHORT);
  229. void        DisplaySession (PBUFFHEADER);
  230. void         DisplayProcessTree (USHORT, USHORT, PBUFFHEADER);
  231. void         DisplayProcess (PBUFFHEADER);
  232. void        PrintSharedMemoryInfo (PSHRMEMINFO);
  233. void        PrintSemaphoreInfo (PSEMINFO);
  234. void        PrintTaskHeader (void);
  235. void        PrintThreadInfo (PTHREADINFO, USHORT);
  236. void        PrintUsage (void);
  237. void        PrintModuleInfo (PMODINFO);
  238. char        *ConvertPathToFormat (char *);
  239. char        *GetModuleName (USHORT);
  240. void        main (int, char **);
  241. #ifdef __OS2__
  242. int        getopt (int, char **, char *);
  243. #endif
  244.  
  245. /*
  246.  * Globals
  247.  */
  248.  
  249. #ifdef __OS2__
  250. int        optind = 1;
  251. char        *optarg = (char *)NULL;
  252. #endif
  253.  
  254. bool        RequireHeader = TRUE;
  255. size_t        count = 0;        /* Number of processes        */
  256. PPROCESSINFO    *ListOfProcesses;    /* Process list            */
  257. bool        F_flag = FALSE;        /* Full file names        */
  258. bool        t_flag = FALSE;        /* Print Thread info        */
  259. bool        o_flag = FALSE;        /* Order info             */
  260. bool        n_flag = FALSE;        /* Do not Print Process tree    */
  261. bool        l_flag = FALSE;        /* Full flag            */
  262. char        *ProcessName = (char *)NULL;
  263.  
  264. #ifndef __OS2__
  265. PBUFFHEADER     BasePS;
  266. #endif
  267.  
  268. /*
  269.  * OS/2 Process Types
  270.  */
  271.  
  272. char        *ProcessTypes[] = {
  273.     " DEF", "FULL", " WIN", "  PM", " VDM",
  274.     " GRP", " DLL", "WVDM", " PDD", " VDD"
  275. };
  276.  
  277. char        *ThreadState[] = {
  278.     "", "Ready", "Blocked", "", "", "Running"
  279. };
  280.  
  281. /*
  282.  * Display Process Tree
  283.  */
  284.  
  285. void    DisplayProcessTree (USHORT pid, USHORT indent, PBUFFHEADER ps)
  286. {
  287.     PPROCESSINFO    ppiLocal = PTR (ps->ppi);
  288.  
  289.     while (ppiLocal->ulEndIndicator != PROCESS_END_INDICATOR)
  290.     {
  291.     if ((indent && (ppiLocal->pidParent == pid)) ||
  292.         ((!indent) && (ppiLocal->pid == pid)))
  293.         PrintProcessEntry (ppiLocal, indent, ps);
  294.  
  295. /* Go to the next Process Block */
  296.  
  297.         ppiLocal = (PPROCESSINFO) PTR (ppiLocal->ptiFirst +
  298.                        ppiLocal->usThreadCount);
  299.     }
  300. }
  301.  
  302. /*
  303.  * Print the Process Tree
  304.  */
  305.  
  306. void    main (int argc, char **argv)
  307. {
  308.     USHORT        rc;
  309.     PBUFFHEADER        ps;
  310.     int            c;
  311.     bool        S_flag = FALSE;
  312.     bool        M_flag = FALSE;
  313.     bool        m_flag = FALSE;
  314.     bool        a_flag = FALSE;
  315.     char        *D_FileName = (char *)NULL;
  316.     char        *L_FileName = (char *)NULL;
  317.  
  318.     while ((c = getopt (argc, argv, "oalmMSnFtD:L:")) != EOF)
  319.     {
  320.         switch (c)
  321.     {
  322.         case 'F':    F_flag = TRUE;        break;
  323.         case 't':    t_flag = TRUE;        break;
  324.         case 'o':    o_flag = TRUE;        break;
  325.         case 'S':    S_flag = TRUE;        break;
  326.             case 'M':    M_flag = TRUE;        break;
  327.         case 'n':    n_flag = TRUE;        break;
  328.         case 'm':    m_flag = TRUE;        break;
  329.         case 'l':    l_flag = TRUE;        break;
  330.         case 'a':    a_flag = TRUE;        break;
  331.         case 'D':    D_FileName = optarg;    break;
  332.         case 'L':    L_FileName = optarg;    break;
  333.  
  334.         default:    PrintUsage ();
  335.     }
  336.     }
  337.  
  338. /* Get process info */
  339.  
  340.     if ((ps = (PBUFFHEADER)malloc (0x8000)) == (PBUFFHEADER)NULL)
  341.     {
  342.         fputs ("ps: Out of memory\n", stderr);
  343.     exit (1);
  344.     }
  345.  
  346. #ifndef __OS2__
  347.     BasePS = ps;
  348. #endif
  349.  
  350. /* Load information */
  351.  
  352.     if (L_FileName != (char *)NULL)
  353.     {
  354.     int    Fid = open (L_FileName, O_RDONLY | O_BINARY);
  355.  
  356.     if (Fid < 0)
  357.     {
  358.         fprintf (stderr, "ps: Cannot open %s (%d)\n", L_FileName, errno);
  359.         exit (1);
  360.     }
  361.  
  362.     if ((unsigned)read (Fid, ps, 0x8000) != 0x8000)
  363.     {
  364.         fprintf (stderr, "ps: Read error on %s (%d)\n", L_FileName, errno);
  365.         exit (1);
  366.     }
  367.  
  368.     close (Fid);
  369.     }
  370.  
  371. /* Get info from system */
  372.  
  373.     else if (rc = Dos32QProcStatus (ps, 0x8000))
  374.     {
  375.     fprintf (stderr, "ps: DosQProcStatus failed (%d)\n", rc);
  376.     exit (1);
  377.     }
  378.  
  379. /* Dump the info */
  380.  
  381.     if (D_FileName != (char *)NULL)
  382.     {
  383.         int    Fid = open (D_FileName,
  384.                 O_CREAT | O_TRUNC | O_WRONLY | O_BINARY,
  385.                 S_IWRITE | S_IREAD);
  386.  
  387.     if (Fid < 0)
  388.     {
  389.         fprintf (stderr, "ps: Cannot create %s (%d)\n", D_FileName, errno);
  390.         exit (1);
  391.     }
  392.  
  393.     if ((unsigned)write (Fid, ps, 0x8000) != 0x8000)
  394.         fprintf (stderr, "ps: Write error on %s (%d)\n", D_FileName, errno);
  395.  
  396.     close (Fid);
  397.     }
  398.  
  399. /* Advance */
  400.  
  401.     argc -= optind;
  402.     argv += optind;
  403.  
  404. /* Print Semaphore info ? */
  405.  
  406.     if (S_flag)
  407.     PrintSemaphoreInfo (PTR (ps->psi));
  408.  
  409. /* Print Shared memory info ? */
  410.  
  411.     if (M_flag)
  412.     PrintSharedMemoryInfo (PTR (ps->psmi));
  413.  
  414. /* Print Module info ? */
  415.  
  416.     if (m_flag)
  417.     PrintModuleInfo (PTR (ps->pmi));
  418.  
  419. /* Print all process info ? */
  420.  
  421.     if (a_flag)
  422.     DisplayAllProcess (ps);
  423.  
  424. /* anything else */
  425.  
  426.     if (((a_flag | S_flag | M_flag | m_flag) || (D_FileName != (char *)NULL)) &&
  427.         !argc)
  428.     exit (0);
  429.  
  430. /* Session Info */
  431.  
  432.     if (!argc)
  433.     {
  434.     DisplaySession (ps);
  435.         exit (0);
  436.     }
  437.  
  438. /* A specific process ? */
  439.  
  440.     if (argc != 1)
  441.         PrintUsage ();
  442.  
  443.     PrintTaskHeader ();
  444.  
  445.     if (isdigit (**argv))
  446.     DisplayProcessTree (atoi (argv[0]), 0, ps);
  447.  
  448.     else
  449.     {
  450.     ProcessName = *argv;
  451.     DisplayProcess (ps);
  452.     }
  453.  
  454.     exit (0);
  455. }
  456.  
  457. /*
  458.  * Print usage
  459.  */
  460.  
  461. void    PrintUsage (void)
  462. {
  463.     fputs ("usage: ps [ -L name ] [ -D name ] [ -SMm ] [[ -oalFtn ] pid]\n",
  464.            stderr);
  465.     exit (1);
  466. }
  467.  
  468. /*
  469.  * Covert to UNIX format
  470.  */
  471.  
  472. char *ConvertPathToFormat (char *path)
  473. {
  474.     char    *s = path;
  475.  
  476.     while ((path = strchr (path, '\\')) != (char *)NULL)
  477.     *path = '/';
  478.  
  479.     return s;
  480. }
  481.  
  482. /*
  483.  * Get Module name
  484.  */
  485.  
  486. char    *GetModuleName (USHORT hModRef)
  487. {
  488.     static char        name[PATH_MAX + NAME_MAX + 3];
  489.     char        *pName;
  490.  
  491. #ifdef __OS2__
  492.     if (DosQueryModuleName (hModRef, sizeof (name), name))
  493. #else
  494.     if (DosGetModName (hModRef, sizeof (name), name))
  495. #endif
  496.     strcpy(name, "<unknown>");
  497.     
  498.     ConvertPathToFormat (name);
  499.  
  500.     return (!F_flag && ((pName = strrchr (name, '/')) != (char *)NULL))
  501.        ? ++pName : name;
  502. }
  503.  
  504. /*
  505.  * Getopt
  506.  */
  507.  
  508. #ifdef __OS2__
  509. int    getopt (int argc, char **argv, char *optstring)
  510. {
  511.     int        cur_option;        /* Current option        */
  512.     char    *cp;            /* Character pointer        */
  513.     static int    GetOptionPosition = 1;
  514.  
  515.     if (GetOptionPosition == 1)
  516.     {
  517.  
  518. /* Check for out of range, correct start character and not single */
  519.  
  520.     if ((optind >= argc) || (*argv[optind] != '-') || !argv[optind][1])
  521.         return EOF;
  522.  
  523.     if (!strcmp (argv[optind], "--"))
  524.         return EOF;
  525.     }
  526.  
  527. /* Get the current character from the current argument vector */
  528.  
  529.     cur_option = argv[optind][GetOptionPosition];
  530.  
  531. /* Validate it */
  532.  
  533.     if ((cur_option == ':') ||
  534.     ((cp = strchr (optstring, cur_option)) == (char *)NULL))
  535.     {
  536.  
  537. /* Move to the next offset */
  538.  
  539.     if (!argv[optind][++GetOptionPosition])
  540.     {
  541.         optind++;
  542.         GetOptionPosition = 1;
  543.     }
  544.  
  545.     return '?';
  546.     }
  547.  
  548. /* Parameters following ? */
  549.  
  550.     optarg = (char *)NULL;
  551.  
  552.     if (*(++cp) == ':')
  553.     {
  554.     if (argv[optind][GetOptionPosition + 1])
  555.         optarg = &argv[optind++][GetOptionPosition + 1];
  556.  
  557.     else if (++optind >= argc)
  558.     {
  559.         optarg = (char *)NULL;
  560.         GetOptionPosition = 1;
  561.         return '?';
  562.     }
  563.  
  564.     else
  565.         optarg = argv[optind++];
  566.  
  567.     GetOptionPosition = 1;
  568.     }
  569.  
  570.     else if (!argv[optind][++GetOptionPosition])
  571.     {
  572.     GetOptionPosition = 1;
  573.     optind++;
  574.     }
  575.  
  576.     return cur_option;
  577. }
  578. #endif
  579.  
  580. /*
  581.  * PrintThread Info
  582.  */
  583.  
  584. void    PrintThreadInfo (PTHREADINFO ptiFirst, USHORT usThreadCount)
  585. {
  586.     USHORT    i;
  587.  
  588.     puts ("\t\t TID Slot Sleep         Pri  STim  UTim State");
  589.  
  590.     for (i = 0; i < usThreadCount; i++)
  591.     {
  592.     printf ("\t\t%4d %4d 0x%.8lx 0x%.4lx %5ld %5ld %s (0x%x)\n",
  593.         ptiFirst->tidWithinProcess,
  594.         ptiFirst->usSlot,
  595.         ptiFirst->ulBlockId,
  596.         ptiFirst->ulPriority,
  597.         ptiFirst->ulSysTime,
  598.         ptiFirst->ulUserTime,
  599.         ptiFirst->uchState <= 5 ? ThreadState[ptiFirst->uchState]
  600.                     : "unknown",
  601.         ptiFirst->uchState);
  602.  
  603.         ptiFirst++;
  604.     }
  605.  
  606.     RequireHeader = TRUE;
  607. }
  608.  
  609. /*
  610.  * Print Semaphore Information
  611.  */
  612.  
  613. void    PrintSemaphoreInfo (PSEMINFO psi)
  614. {
  615.     psi = (PSEMINFO)(((char *)psi) + 16);
  616.     puts ("   TID Flags RefC ReqC   Index Name");
  617.  
  618.     while (psi != (PSEMINFO)NULL)
  619.     {
  620.     psi = PTR (psi);
  621.  
  622.     if (!psi->pNext)
  623.         break;
  624.  
  625.     printf ("0x%.4x  0x%.2x  %3d  %3d  0x%.4x \\S%s (0x%.2x%.2x%.2x)\n",
  626.         psi->idOwningThread,
  627.         psi->fbFlags,
  628.         psi->uchReferenceCount,
  629.         psi->uchRequestCount,
  630.         psi->usIndex,
  631.         psi->szSemName,
  632.         psi->ucReserved[0],
  633.         psi->ucReserved[1],
  634.         psi->ucReserved[2]);
  635.  
  636.     psi = psi->pNext;
  637.     }
  638. }
  639.  
  640. /*
  641.  * Print Shared Memory Information
  642.  */
  643.  
  644. void    PrintSharedMemoryInfo (PSHRMEMINFO psmi)
  645. {
  646.     puts ("   Hdl    Sel RefC Name");
  647.  
  648.     while (psmi != (PSHRMEMINFO)NULL)
  649.     {
  650.     psmi = PTR (psmi);
  651.  
  652.     if (!psmi->pNext)
  653.         break;
  654.  
  655.     printf ("0x%.4x 0x%.4x  %3d %s\n",
  656.         psmi->usMemHandle,
  657.         psmi->selMem,
  658.         psmi->usReferenceCount,
  659.         psmi->szMemName);
  660.  
  661.     psmi = psmi->pNext;
  662.     }
  663. }
  664.  
  665. /*
  666.  * Print Module Information
  667.  */
  668.  
  669. void    PrintModuleInfo (PMODINFO pmi)
  670. {
  671.     puts ("Type   RefC SegC     hMod Name");
  672.  
  673.     while (pmi != (PMODINFO)NULL)
  674.     {
  675.     pmi = PTR (pmi);
  676.  
  677.     if (!pmi->pNext)
  678.         break;
  679.  
  680.     printf ("  %2d %6ld  %3ld [0x%.4x] %s\n",
  681.         pmi->usModType ? 32 : 16,
  682.         pmi->ulModRefCount,
  683.         pmi->ulSegmentCount,
  684.             pmi->hMod,
  685.             PTR (pmi->szModName));
  686.  
  687.     pmi = pmi->pNext;
  688.     }
  689. }
  690.  
  691. /*
  692.  * Display a process by name
  693.  */
  694.  
  695. void    DisplayProcess (PBUFFHEADER ps)
  696. {
  697.     PPROCESSINFO    ppiLocal = PTR (ps->ppi);
  698.     char        *pName;
  699.  
  700.     strlwr (ProcessName);
  701.  
  702.     while (ppiLocal->ulEndIndicator != PROCESS_END_INDICATOR)
  703.     {
  704.     pName = strlwr (GetModuleName (ppiLocal->hModRef));
  705.  
  706.     if (strstr (pName, ProcessName) != (char *)NULL)
  707.         PrintProcessEntry (ppiLocal, 0, ps);
  708.  
  709.         ppiLocal = (PPROCESSINFO) PTR (ppiLocal->ptiFirst +
  710.                        ppiLocal->usThreadCount);
  711.     }
  712. }
  713.  
  714. /*
  715.  * Print An entry in the process table
  716.  */
  717.  
  718. void     PrintProcessEntry (PPROCESSINFO ppiLocal, USHORT indent,
  719.                 PBUFFHEADER ps)
  720. {
  721.     USHORT        prty;
  722.  
  723.     if (Dos32GetPrty (PRTYS_PROCESS, &prty, ppiLocal->pid))
  724.     prty = 0;
  725.  
  726.     PrintTaskHeader ();
  727.  
  728.     if (l_flag)
  729.     printf ("%5d %5d %3d %s  0x%.3lx %5ld 0x%.3lx %5d %5d %5d 0x%.3x 0x%.4x %*s%s\n",
  730.         ppiLocal->pid,
  731.         ppiLocal->pidParent,
  732.         ppiLocal->usThreadCount,
  733.         ppiLocal->ulType <= 9 ? ProcessTypes[ppiLocal->ulType] : " ?? ",
  734.         ppiLocal->ulStatus,
  735.         ppiLocal->idSession,
  736.         ppiLocal->ulSessionType,
  737.         ppiLocal->usSem16Count,
  738.         ppiLocal->usDllCount,
  739.         ppiLocal->usShrMemHandles,
  740.         ppiLocal->usReserved,
  741.         prty, indent, "", GetModuleName (ppiLocal->hModRef));
  742.  
  743.     else
  744.     printf ("%5d %5d %3d %s  0x%.3lx %5ld 0x%.4x %*s%s\n",
  745.         ppiLocal->pid,
  746.         ppiLocal->pidParent,
  747.         ppiLocal->usThreadCount,
  748.         ppiLocal->ulType <= 9 ? ProcessTypes[ppiLocal->ulType] : " ?? ",
  749.         ppiLocal->ulStatus,
  750.         ppiLocal->idSession,
  751.         prty, indent, "", GetModuleName (ppiLocal->hModRef));
  752.  
  753.     if (t_flag)
  754.     PrintThreadInfo (PTR (ppiLocal->ptiFirst), ppiLocal->usThreadCount);
  755.  
  756. /* Remove repeats on display all */
  757.  
  758.     if (count)
  759.     RemoveProcessEntry (ppiLocal->pid);
  760.  
  761.     if (!n_flag)
  762.     DisplayProcessTree (ppiLocal->pid, indent + 2, ps);
  763. }
  764.  
  765. /*
  766.  * Output Task header
  767.  */
  768.  
  769. void    PrintTaskHeader (void)
  770. {
  771.     if (!RequireHeader)
  772.         return;
  773.  
  774.     if (l_flag)
  775.     puts ("\n  PID  PPID  TC TYPE STATUS   SID STYPE   Sem  DLLs  Smem          PRI Program");
  776.  
  777.     else
  778.     puts ("\n  PID  PPID  TC TYPE STATUS   SID    PRI Program");
  779.  
  780.     RequireHeader = FALSE;
  781. }
  782.  
  783. /*
  784.  * Display All process by name
  785.  */
  786.  
  787. void    DisplayAllProcess (PBUFFHEADER ps)
  788. {
  789.     PPROCESSINFO    ppiLocal = PTR (ps->ppi);
  790.     PSUMMARY        pSumm = PTR (ps->psumm);
  791.     size_t        i;
  792.  
  793. /* Count the proceses */
  794.  
  795.     count = 0;
  796.  
  797.     while (ppiLocal->ulEndIndicator != PROCESS_END_INDICATOR)
  798.     {
  799.     count++;
  800.         ppiLocal = (PPROCESSINFO) PTR (ppiLocal->ptiFirst +
  801.                        ppiLocal->usThreadCount);
  802.     }
  803.  
  804. /* Build array */
  805.  
  806.     if ((ListOfProcesses = (PPROCESSINFO *)malloc (sizeof (PPROCESSINFO) *
  807.                            count))
  808.                 == (PPROCESSINFO *)NULL)
  809.     {
  810.         fputs ("ps: Out of memory\n", stderr);
  811.     exit (1);
  812.     }
  813.  
  814. /* Build the list */
  815.  
  816.     ppiLocal = PTR (ps->ppi);
  817.     count = 0;
  818.  
  819.     while (ppiLocal->ulEndIndicator != PROCESS_END_INDICATOR)
  820.     {
  821.     ListOfProcesses[count++] = ppiLocal;
  822.         ppiLocal = (PPROCESSINFO) PTR (ppiLocal->ptiFirst +
  823.                        ppiLocal->usThreadCount);
  824.     }
  825.  
  826.     if (o_flag)
  827.     qsort ((void *)ListOfProcesses, count, sizeof (PPROCESSINFO),
  828.            SortProcesses);
  829.  
  830. /* Display list - no repeats */
  831.  
  832.     for (i = 0; i < count; i++)
  833.     {
  834.     if (ListOfProcesses[i] != (PPROCESSINFO)NULL)
  835.         PrintProcessEntry (ListOfProcesses[i], 0, ps);
  836.     
  837.     ListOfProcesses[i] = (PPROCESSINFO)NULL;
  838.     }
  839.  
  840.     printf ("System reports: %ld Threads, %ld Processes, %ld Modules\n",
  841.             pSumm->ulThreadCount, pSumm->ulProcessCount, pSumm->ulModuleCount);
  842. }
  843.  
  844. /*
  845.  * Sort function
  846.  */
  847.  
  848. int    SortProcesses (const void *p1, const void *p2)
  849. {
  850.     if ((*(PPROCESSINFO *)p1)->pid > (*(PPROCESSINFO *)p2)->pid)
  851.         return 1;
  852.  
  853.     else if ((*(PPROCESSINFO *)p1)->pid < (*(PPROCESSINFO *)p2)->pid)
  854.         return -1;
  855.  
  856.     return 0;
  857. }
  858.  
  859. /*
  860.  * Remove entry function
  861.  */
  862.  
  863. void    RemoveProcessEntry (USHORT pid)
  864. {
  865.     size_t    i;
  866.  
  867.     for (i = 0; i < count; i++)
  868.     {
  869.     if ((ListOfProcesses[i] != (PPROCESSINFO)NULL) &&
  870.         (ListOfProcesses[i]->pid == pid))
  871.         ListOfProcesses[i] = (PPROCESSINFO)NULL;
  872.     }
  873. }
  874.  
  875. /*
  876.  * Display the processes in the current session
  877.  */
  878.  
  879. void    DisplaySession (PBUFFHEADER ps)
  880. {
  881.     PPROCESSINFO    ppiMy;
  882.     ULONG        MySession;
  883.     USHORT        MyPid = getpid();
  884.     USHORT        ParentPid = MyPid;
  885.     USHORT        SessionParentPid = MyPid;
  886.  
  887. /* Find the parent for the current session */
  888.  
  889.     while (TRUE)
  890.     {
  891.     if ((ppiMy = FindPidEntry (ps, ParentPid)) == (PPROCESSINFO)NULL)
  892.     {
  893.         if (ParentPid != MyPid)
  894.             break;
  895.  
  896.         fprintf (stderr,
  897.              "ps: Cannot find process information for self (%d)\n",
  898.              ParentPid);
  899.         exit (1);
  900.     }
  901.  
  902. /* First time round ? - yes save session number */
  903.  
  904.     if (ParentPid == MyPid)
  905.         MySession = ppiMy->idSession;
  906.  
  907.     else if (MySession != ppiMy->idSession)
  908.         break;
  909.  
  910. /* Still in same session, now find the parent */
  911.  
  912.     SessionParentPid = ParentPid;
  913.     ParentPid = ppiMy->pidParent;
  914.     }
  915.  
  916. /* Now display the session info */
  917.  
  918.     DisplayProcessTree (SessionParentPid, 0, ps);
  919. }
  920.  
  921.  
  922. /*
  923.  * Find the entry for a PID
  924.  */
  925.  
  926. PPROCESSINFO    FindPidEntry (PBUFFHEADER ps, USHORT pid)
  927. {
  928.     PPROCESSINFO    ppiLocal = PTR (ps->ppi);
  929.  
  930.     while (ppiLocal->ulEndIndicator != PROCESS_END_INDICATOR)
  931.     {
  932.     if (ppiLocal->pid == pid)
  933.         return ppiLocal;
  934.  
  935.         ppiLocal = (PPROCESSINFO) PTR (ppiLocal->ptiFirst +
  936.                        ppiLocal->usThreadCount);
  937.     }
  938.  
  939.     return (PPROCESSINFO)NULL;
  940. }
  941.  
  942. /*
  943.  * Specials for EMX
  944.  */
  945.  
  946. #if defined (__EMX__)
  947. USHORT    Dos32GetPrty (USHORT usScope, PUSHORT pusPriority, USHORT pid)
  948. {
  949.     return ((USHORT)
  950.         (_THUNK_PROLOG (2 + 4 + 2);
  951.          _THUNK_SHORT (usScope);
  952.          _THUNK_FLAT (pusPriority);
  953.          _THUNK_SHORT (pid);
  954.          _THUNK_CALL (Dos16GetPrty)));
  955. }
  956.  
  957. USHORT    Dos32QProcStatus (PVOID pvProcData, USHORT usSize)
  958. {
  959.     return ((USHORT)
  960.         (_THUNK_PROLOG (4 + 2);
  961.          _THUNK_FLAT (pvProcData);
  962.          _THUNK_SHORT (usSize);
  963.          _THUNK_CALL (Dos16QProcStatus)));
  964. }
  965. #endif
  966.